// 整合未来之窗渲染引擎到cq库
; (function(cq) {
    "use strict";
    
    // 渲染引擎默认配置
    var renderConfig = {
        open: "{cwpdapp{",
        close: "}}"
    };
    
    // 工具函数
    var utils = {
        exp: function(a) {
            return new RegExp(a, "g")
        },
        query: function(a, c, e) {
            var f = ["#([\\s\\S])+?", "([^{#}])*?"][a || 0];
            return this.exp((c || "") + renderConfig.open + f + renderConfig.close + (e || ""))
        },
        escape: function(a) {
            return String(a || "").replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/'/g, "&#39;")
                .replace(/"/g, "&quot;")
        },
        error: function(a, b) {
            var c = "未来之窗渲染引擎 Error：";
            if (typeof console !== "undefined" && console.error) {
                console.error(c + a + "\n" + (b || ""));
            }
            return c + a;
        }
    };
    
    // 渲染器构造函数
    function RenderEngine(tpl) {
        this.tpl = tpl;
        this.cache = null;
    }
    
    // 渲染器原型方法
    RenderEngine.prototype = {
        parse: function(data) {
            var tpl = this.tpl;
            var openTag = utils.exp("^" + renderConfig.open + "#", "");
            var closeTag = utils.exp(renderConfig.close + "$", "");
            
            // 处理模板字符串
            var code = tpl.replace(/[\r\t\n]/g, " ")
                .replace(utils.exp(renderConfig.open + "#"), renderConfig.open + "# ")
                .replace(utils.exp(renderConfig.close + "}"), "} " + renderConfig.close)
                .replace(/\\/g, "\\\\")
                .replace(/(?="|')/g, "\\")
                .replace(utils.query(), function(match) {
                    match = match.replace(openTag, "").replace(closeTag, "");
                    return '";' + match.replace(/\\/g, "") + '; view+="'
                })
                .replace(utils.query(1), function(match) {
                    var prefix = '"+(';
                    match = match.replace(utils.exp(renderConfig.open + "|" + renderConfig.close), "");
                    
                    // 处理=开头的表达式
                    if (/^=/.test(match)) {
                        match = match.replace(/^=/, "");
                        prefix = '"+utils.escape(';
                    }
                    return prefix + match.replace(/\\/g, "") + ')+"';
                });
            
            // 包装成函数
            code = '"use strict";var view = "' + code + '";return view;';
            
            try {
                this.cache = new Function("d", "utils", code);
                return this.cache(data, utils);
            } catch (e) {
                delete this.cache;
                return utils.error(e, tpl);
            }
        },
        
        render: function(data, callback) {
            if (!data) {
                return utils.error("没有提供渲染数据");
            }
            
            var result = this.cache ? this.cache(data, utils) : this.parse(data);
            
            if (callback && typeof callback === "function") {
                callback(result);
                return;
            }
            
            return result;
        }
    };
    
    // 添加到cq命名空间
    cq.render = function(tpl) {
        if (typeof tpl !== "string") {
            return utils.error("模板必须是字符串类型");
        }
        return new RenderEngine(tpl);
    };
    
    // 全局配置方法
    cq.render.config = function(options) {
        if (options && typeof options === "object") {
            if (options.open) renderConfig.open = options.open;
            if (options.close) renderConfig.close = options.close;
        }
        return renderConfig;
    };
    
    // 扩展cq原型，支持直接从选择器获取模板
    cq.prototype.render = function(data, callback) {
        if (this.elements.length === 0) {
            return utils.error("没有找到匹配的元素作为模板");
        }
        
        // 获取第一个元素的HTML作为模板
        var tpl = this.elements[0].innerHTML;
        return cq.render(tpl).render(data, callback);
    };
    
})(window.$cq);
